package com.shelpe.services.simbasync.service.impl;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.shelpe.services.simbasync.dao.RptCustomerMapper;
import com.shelpe.services.simbasync.dao.RptCustomerRealtimeMapper;
import com.shelpe.services.simbasync.dao.SubwayTokensMapper;
import com.shelpe.services.simbasync.dao.UserNickHashMapper;
import com.shelpe.services.simbasync.dao.UsersMapper;
import com.shelpe.services.simbasync.exception.ApiException;
import com.shelpe.services.simbasync.model.RptCustomer;
import com.shelpe.services.simbasync.model.RptCustomerExample;
import com.shelpe.services.simbasync.model.RptCustomerRealtime;
import com.shelpe.services.simbasync.model.SubwayTokens;
import com.shelpe.services.simbasync.model.UserNickHash;
import com.shelpe.services.simbasync.model.UserNickHashExample;
import com.shelpe.services.simbasync.model.Users;
import com.shelpe.services.simbasync.model.UsersExample;
import com.shelpe.services.simbasync.model.UsersWithBLOBs;
import com.shelpe.services.simbasync.service.UserService;
import com.shelpe.services.simbasync.service.simbaproxy.OrderProxy;
import com.shelpe.services.simbasync.service.simbaproxy.UserProxy.RptCustomerRealTimeDto;
import com.shelpe.services.simbasync.util.Util;


@Service
public class UserServiceImpl implements UserService{

	private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
	
	@Autowired
	private RptCustomerMapper rptcusmapper;
	
	@Autowired
	private UsersMapper userMapper;
	
	@Autowired
	private SubwayTokensMapper tokenMapper;
	
	@Autowired
	private RptCustomerRealtimeMapper rptRealTime;
	
	@Autowired
	private UserNickHashMapper userNickHashMapper;
	
	@Autowired
	private OrderProxy orderProxy;
	
	@Value("${simbasync.articleCode}")
	private String articleCode;
	
	
	@Override
	public int countAll(){
		
		UsersExample example = new UsersExample();
		
		return userMapper.countByExample(example);
	}
	
	@Override
	public Long createAndAddProxyUser(UsersWithBLOBs user){
		
		UserNickHashExample example = new UserNickHashExample();
		example.createCriteria().andNickEqualTo(user.getNick());
		List<UserNickHash> addUserHashs = userNickHashMapper.selectByExample(example);//校验
		if(addUserHashs == null || addUserHashs.size() == 0){
			UserNickHash userHash = new UserNickHash();
			userHash.setNick(user.getNick());
			userNickHashMapper.insertSelective(userHash);
		}
		
		addUserHashs = userNickHashMapper.selectByExample(example);
		if(addUserHashs != null && addUserHashs.size() > 0){
			Integer newUserId = addUserHashs.iterator().next().getUserId();
			long temp = Long.valueOf(newUserId.toString());
			user.setUserId(-temp);
		}else{
			logger.warn("createAndAddUser, maybe something is wrong, nick {}", user.getNick());
			return null;
		}

		initUser(user);
		int num = userMapper.insert(user);
		
		return num > 0 ? user.getUserId() : null;
	}
	
	public int createAndAddPurchaseUser(UsersWithBLOBs user){
		
		initUser(user);
		user.setUserType(Byte.valueOf("1"));//订购用户
		String response = orderProxy.getSubscribeRelation(user.getNick(), articleCode);
		if(response != null && response.contains("vas_subscribe_get_response")){
			
			JSONObject object = JSON.parseObject(response);
			JSONObject objRes = object==null? null : object.getJSONObject("vas_subscribe_get_response");
			JSONObject objItems = objRes==null? null : objRes.getJSONObject("article_user_subscribes");
			JSONArray jsonList = objItems==null? null : objItems.getJSONArray("article_user_subscribe");
			
			if(jsonList != null && jsonList.size() > 0){
				
				JSONObject item = jsonList.getJSONObject(0);
				if(item != null && item.containsKey("item_code")){
					user.setItemCode(item.getString("item_code"));
				}
				
				if(item != null && item.containsKey("deadline")){
					user.setPurchaseExpires(item.getDate("deadline"));
				}
			}
		}else{
			logger.warn("createAndAddPurchaseUser, userId {}, response {}", user.getUserId(), response);
		}
		
		return userMapper.insertSelective(user);
	}
	
	@Override
	public int updateUser(Users user){
		
		return userMapper.updateByPrimaryKey(user);
	}
	
	@Override 
	public int updateUserSelective(Users user){
		UsersWithBLOBs usersB = new UsersWithBLOBs();
		BeanUtils.copyProperties(user, usersB);
		return userMapper.updateByPrimaryKeySelective(usersB);
	}
	
	@Override
	public int countRptCustomerByDate(Date date){
		RptCustomerExample example = new RptCustomerExample();
		example.createCriteria().andDateEqualTo(date);
		
		return rptcusmapper.countByExample(example);
	}
	
	@Override
	public int countRptCustomerByUserIdDate(long userId, Date date){
		RptCustomerExample example = new RptCustomerExample();
		example.createCriteria()
				.andTaobaoUserIdEqualTo(userId)
				.andDateEqualTo(date);
		
		return rptcusmapper.countByExample(example); 
	}
	
	@Override
	public int addRptCustomer(RptCustomer rpt) {
		// TODO Auto-generated method stub
		return rptcusmapper.insert(rpt);
	}

	@Override
	public int addRptCustomerList(List<RptCustomer> rptList) {
		// TODO Auto-generated method stub
		int num = 0;
		for(RptCustomer item : rptList){
			num += rptcusmapper.insert(item);
		}
		return num;
	}
	
	@Override
	public int deleteRptCustomerByDateRange(List<Long> userIds, Date startDate, Date endDate){
		RptCustomerExample example = new RptCustomerExample();
		example.createCriteria()
		.andDateBetween(startDate, endDate)
		.andTaobaoUserIdIn(userIds);
		
		return rptcusmapper.deleteByExample(example);
	}
	
	@Override
	public int insertRptCustomerBatch(List<RptCustomer> rptList){
		 int num = 0;
		 int pageSize = 15000;
		 if(rptList != null && rptList.size() > 0){
			
			 int fromIndex = 0;		
			 int endIndex = 0;		
			 do{	
				 endIndex += pageSize; 			
				 if(endIndex > rptList.size()){		
					 endIndex = rptList.size();				
				 }
				 num += rptcusmapper.insertBatch(rptList.subList(fromIndex, endIndex));	
				 fromIndex += pageSize; 
	
			 }while(fromIndex < rptList.size());	
		 }
		 
		 return num;
	}

	@Override
	public Date getLastTimeFromRpt(long userId) {
		// TODO Auto-generated method stub
		return rptcusmapper.getLastTimeFromRpt(userId);
	}

	@Override
	public List<RptCustomer> parseJsonToRptCustomerBase(String response) {
		// TODO Auto-generated method stub

		List<RptCustomer> ret = new ArrayList<RptCustomer>();
		
		if(response != null && response.contains("simba_rpt_custbase_get_response")){
			JSONObject object = JSON.parseObject(response);
			JSONObject objRes = object==null? null : object.getJSONObject("simba_rpt_custbase_get_response");
			JSONArray jsonList = objRes==null? null : objRes.getJSONArray("rpt_cust_base_list");
			int size = jsonList == null? 0 : jsonList.size();
			
			for(int i = 0; i < size; i++){
				JSONObject item = jsonList.getJSONObject(i);
				RptCustomer rpt = new RptCustomer();
				
				int impression = NumberUtils.toInt(item.getString("impressions"), 0);
				int cost = NumberUtils.toInt(item.getString("cost"), 0);
				int click = NumberUtils.toInt(item.getString("click"), 0);
				int aclick = NumberUtils.toInt(item.getString("aclick"), 0);
				float ctr = NumberUtils.toFloat(item.getString("ctr"), 0.0f);
				float cpc = NumberUtils.toFloat(item.getString("cpc"), 0.0f);
				float cpm = NumberUtils.toFloat(item.getString("cpm"), 0.0f);
				
				rpt.setCpc(cpc);
				rpt.setCtr(ctr) ;
				rpt.setImpressions(impression) ;
				rpt.setCpm(cpm);
				rpt.setClick(click);
				rpt.setCost(cost) ;	
				rpt.setDate(item.getDate("date"));	
				rpt.setSource(item.getByte("source"));
				rpt.setAclick(aclick);
				
				rpt.setDirectPay(0);
				rpt.setIndirectPay(0); 
				rpt.setDirectPayCount(0);
				rpt.setIndirectPayCount(0);
				rpt.setFavShopCount(0);
				rpt.setFavItemCount(0); 	
				
				ret.add(rpt);
			}
		}else{
			logger.warn("can not get any info from proxy, maybe something is wrong, api is parseJsonToRptCustomerBase, response: {}", response);
			throw new ApiException();
		}
		
		return ret;
	}

	@Override
	public int combineRptCustomerEffect(String response, Map<String, Integer> lastDayRecord, List<RptCustomer> list) {
		// TODO Auto-generated method stub
		int size = 0;
		int lastDayRecordTotal = 0;
		int lastDayNoDataNum = 0;
		if(response != null && response.contains("simba_rpt_custeffect_get_response")){
			JSONObject object = JSON.parseObject(response);
			JSONObject objRes = object==null? null : object.getJSONObject("simba_rpt_custeffect_get_response");
			JSONArray jsonList = objRes==null? null : objRes.getJSONArray("rpt_cust_effect_list");
			size = jsonList == null? 0 : jsonList.size();
			Date lastDay = Util.getLastDayYYYYMMDD();
			
			for(int i = 0; i < size; i++){
				JSONObject item = jsonList.getJSONObject(i);

				if(item.getDate("date").getTime() == lastDay.getTime()){//前一天的数据会出现这种情况
					lastDayRecordTotal++;
					if(!(item.containsKey("indirectpay") || item.containsKey("favitemcount") || item.containsKey("indirectpaycount") ||
							item.containsKey("favshopcount") || item.containsKey("directpay") || item.containsKey("directpaycount"))){
						//这些都没有，认为没有数据，
						lastDayNoDataNum++;
						continue;
					}
				}
						
				int indirectpay = NumberUtils.toInt(item.getString("indirectpay"), 0);
				int	favItemCount = NumberUtils.toInt(item.getString("favitemcount"), 0);
				int	indirectpaycount = NumberUtils.toInt(item.getString("indirectpaycount"), 0);
				int	favShopCount = NumberUtils.toInt(item.getString("favshopcount"), 0);
				int	directpay = NumberUtils.toInt(item.getString("directpay"), 0);
				int	directpaycount = NumberUtils.toInt(item.getString("directpaycount"), 0);
			
				//根据key找到相关的
				for(RptCustomer rpt : list){
					
					if(rpt.getSource().equals(item.getByte("source")) &&
							rpt.getDate().getTime() == item.getDate("date").getTime()){
					
						rpt.setDirectPay(directpay);
						rpt.setIndirectPay(indirectpay); 
						rpt.setDirectPayCount(directpaycount);
						rpt.setIndirectPayCount(indirectpaycount);
						rpt.setFavShopCount(favShopCount) ;
						rpt.setFavItemCount(favItemCount); 	
						
						break;
					}
				}		
			}
		}else{
			logger.warn("can not get any info from proxy, maybe something is wrong, api is combineRptCustomerEffect, response: {}", response);
			throw new ApiException();
		}
		lastDayRecord.put("total", lastDayRecordTotal);
		lastDayRecord.put("lost", lastDayNoDataNum);
		
		return size;
	}

	@Override
	public void UpdateRptCustomerData(long userId, List<RptCustomer> list) {
		// TODO Auto-generated method stub
			
		for(RptCustomer rpt : list){
			rpt.setTaobaoUserId(userId);
		}
	}

	@Override
	public List<Users> getUserByNick(String nick) {
		// TODO Auto-generated method stub
		UsersExample example = new UsersExample();
		example.createCriteria().andNickEqualTo(nick);	
		List<Users> users = userMapper.selectByExample(example);

		return users;
	}
    
    @Override
    public Long getUserIdByNick(String nick){
        
        List<Users> list = getUserByNick(nick);
        
        if(list != null && list.size()>0){
            return list.iterator().next().getUserId();
        }
        
        return null;
    }
    
    @Override
    public Users getUserByUserId(long userId){
        
        return userMapper.selectByPrimaryKey(userId);
    }
    
    @Override
    public String getNickByUserId(long userId){
        
        Users user = userMapper.selectByPrimaryKey(userId);
        if(user != null){
            return user.getNick();
        }
        
        return null;
    }
	
	@Override
	public List<Users> getAllUsers(){
		UsersExample example = new UsersExample();
		example.createCriteria();
		List<Users> users = userMapper.selectByExample(example);
		
		return users;
	}

	@Override
	public SubwayTokens getSubwayTokenByUserId(long userId) {
		// TODO Auto-generated method stub
		
		return tokenMapper.selectByPrimaryKey(userId);
	}

	@Override
	public SubwayTokens parseJsonToSubwayTokens(String response){
		
		SubwayTokens token = new SubwayTokens();
		
		if(response != null && response.contains("simba_login_authsign_get_response")){
			JSONObject object = JSON.parseObject(response);
			JSONObject res = object == null ? null : object.getJSONObject("simba_login_authsign_get_response");
			String subway = res == null? "" : res.getString("subway_token");
			token.setSubwayToken(subway);
		}else{
			logger.warn("can not get any info from proxy, maybe something is wrong, api is parseJsonToSubwayTokens, response: {}", response);
			throw new ApiException();
		}
		
		token.setReqTs(new Date());
		
		return token;
	}

	@Override
	public int deleteSubwayTokensById(long userId) {
		// TODO Auto-generated method stub
		return tokenMapper.deleteByPrimaryKey(userId);
	}

	@Override
	public int updateSubwayTokens(SubwayTokens token) {
		// TODO Auto-generated method stub
		return tokenMapper.updateByPrimaryKey(token);
	}

	@Override
	public int addSubwayTokens(SubwayTokens token) {
		// TODO Auto-generated method stub
		return tokenMapper.insert(token);
	}
	
	@Override
	public int insertRptCustomerRealtime(RptCustomerRealtime rpt){
		
		return rptRealTime.insert(rpt);	
	}
	
	@Override
	public int insertRptCustomerRealtimeBatch(List<RptCustomerRealtime> list){
		int num = 0;
		if(list != null && list.size() > 0){
			num = rptRealTime.insertBatch(list);
		}
		
		return num;	
	}
	
	@Override
	public void convert(Long userId, List<RptCustomerRealTimeDto> realDto, List<RptCustomerRealtime> rptRealTime){
		
		Date createTime = new Date();
		int size = realDto.size();
		for(int index = 0; index < size; index++){
			RptCustomerRealtime rptItem = new RptCustomerRealtime();
			
			rptItem.setCartTotal(NumberUtils.toInt(realDto.get(index).getCartTotal(), 0));
			rptItem.setClick(NumberUtils.toInt(realDto.get(index).getClick(), 0));
			rptItem.setCost(NumberUtils.toInt(realDto.get(index).getCost(), 0));
			rptItem.setCpc(NumberUtils.toFloat(realDto.get(index).getCpc(), 0.0f));
			rptItem.setCtr(NumberUtils.toFloat(realDto.get(index).getCtr(), 0.0f));
			rptItem.setDirectCartTotal(NumberUtils.toInt(realDto.get(index).getDirectCartTotal(), 0));
			rptItem.setDirectTransaction(NumberUtils.toFloat(realDto.get(index).getDirectTransaction(), 0.0f));
			rptItem.setDirectTransactionShipping(NumberUtils.toInt(realDto.get(index).getDirectTransactionShipping(), 0));
			rptItem.setFavItemTotal(NumberUtils.toInt(realDto.get(index).getFavItemTotal(), 0));
			rptItem.setFavShopTotal(NumberUtils.toInt(realDto.get(index).getFavShopTotal(), 0));
			rptItem.setFavTotal(NumberUtils.toInt(realDto.get(index).getFavTotal(), 0));
			rptItem.setImpression(NumberUtils.toInt(realDto.get(index).getImpression(), 0));
			rptItem.setIndirectCartTotal(NumberUtils.toInt(realDto.get(index).getIndirectCartTotal(), 0));
			rptItem.setIndirectTransaction(NumberUtils.toFloat(realDto.get(index).getIndirectTransaction(), 0.0f));
			rptItem.setIndirectTransactionShipping(NumberUtils.toInt(realDto.get(index).getIndirectTransactionShipping(), 0));
			rptItem.setRoi(NumberUtils.toFloat(realDto.get(index).getRoi(), 0.0f));
			
			rptItem.setTransactionShippingTotal(NumberUtils.toInt(realDto.get(index).getTransactionShippingTotal(), 0));
			rptItem.setTransactionTotal(NumberUtils.toFloat(realDto.get(index).getTransactionTotal(), 0));
			rptItem.setUserId(userId);
			
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			String theDate = realDto.get(index).getTheDate();
			Date temp = new Date();
			
			try {
				temp = sdf.parse(theDate);
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			rptItem.setSource(index);
			rptItem.setTheDate(temp);
			rptItem.setCreateTime(createTime);
			
			rptRealTime.add(rptItem);
		}
		
	}
	
	private void initUser(UsersWithBLOBs user){
		
		String lastDateStr = "1970-01-01 00:00:00";
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		user.setAvatar("");
		user.setBalance(BigDecimal.valueOf(0.00d));
		user.setOther("");
		user.setCid(0);
		user.setCreatedTime(new Date());
		user.setDesc("");
		user.setEmail("");
		user.setInit(Byte.valueOf("1"));
		user.setItemCode("");
		try {
			user.setPurchasedFrom(sdf.parse(lastDateStr));
			user.setPurchaseExpires(sdf.parse(lastDateStr));
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		user.setSex("");
		user.setStatus(true);
		user.setUserType(Byte.valueOf("2"));
		user.setSid(0);
		user.setType("");
		user.setUpdatedTime(new Date());
		user.setAuthorizedUsers("");
	}
	
}